package com.yboot.starter.id.core;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.generator.SnowflakeGenerator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Date;
import java.util.function.Function;

/**
 * 分布式主键生成器工厂。
 */
@Slf4j
public class IdGeneratorUtil {
    private static final String DEFAULT_CACHE_KEY = "idGeneratorFactory:default:";

    /**
     * 单号生成，有序列的id
     *
     * @param prefix
     * @param dateformat
     * @param sequenceLength
     * @param function 校验一下序列自增初始值
     * @return
     * 使用示例 ： entity.setCode(IdGeneratorUtil.createCode(ArchivesProjectConstant.CODE_PREFIX, "yyyy", 4, (key) -> {
     *                 Long num = redisCacheService.get(key, Long.class);
     *                 if (num == null) {
     *                     //获取最新的code
     *                     String code = baseMapper.queryMaxCode(ArchivesProjectConstant.CODE_PREFIX);
     *                     return Long.valueOf(code.substring((ArchivesProjectConstant.CODE_PREFIX + "yyyy").length(), code.length()));
     *                 } else {
     *                     return num;
     *                 }
     *             }));
     */
    public static String createCode(String prefix,
                             String dateformat,
                             int sequenceLength,
                             Function<String, Long> function) {
        if (StrUtil.isBlank(dateformat)) {
            dateformat = "";
        }
        String dateFormat = DateUtil.format(new Date(), dateformat);
        String key = DEFAULT_CACHE_KEY + prefix + dateFormat;
        Long num = 0l;
        try {
            RedisTemplate redisTemplate = SpringUtil.getBean("redisTemplate");
            if (redisTemplate != null) {
                if (redisTemplate.hasKey(key)) {
                    num = redisTemplate.opsForValue().increment(key);
                } else {
                    Long oldNum = function.apply(key);
                    num = oldNum + 1;
                    //序列化的差异long类型会带一个L符号，自增会报错，必须是整数
                    redisTemplate.opsForValue().set(key, num.intValue());
                }
            } else {
                Long oldNum = function.apply(key);
                num = oldNum + 1;
            }
        } catch (Exception e) {
            // Redis异常降级处理：直接使用function获取值
            Long oldNum = function.apply(key);
            num = oldNum + 1;
        }
//        设置合理的过期时间，避免内存泄露
//        LocalDateTime endOfDay = LocalDate.now().atTime(23, 59, 59);
//        long secondsToMidnight = LocalDateTime.now().until(endOfDay, ChronoUnit.SECONDS);
//        redisTemplate.expire(key, secondsToMidnight, TimeUnit.SECONDS);
        StringBuilder codeBuilder = new StringBuilder(String.valueOf(num));
        //往前补0
        while (codeBuilder.length() < sequenceLength) {
            codeBuilder.insert(0,"0");
        }
        return prefix + dateFormat + codeBuilder;
    }


    public static void main(String[] args) {
        String code = IdGeneratorUtil.createCode("AA", "yyyy", 4, (i) -> {
            return 0l;
        });
        System.out.println(code);
        System.out.println(code.substring("AAyyyy".length(), code.length()));
    }
}